package org.batatasframework.support.database;

import java.sql.ResultSet;

import org.batatasframework.support.database.parameters.DatetimeParamenter;
import org.batatasframework.support.database.parameters.DecimalParamenter;
import org.batatasframework.support.database.parameters.NumberParamenter;
import org.batatasframework.support.database.parameters.ObjectParamenter;
import org.batatasframework.support.database.parameters.StringParamenter;
import org.batatasframework.support.database.sql.QueryParameter;
import org.batatasframework.support.database.sql.field.SelectFragment;
import org.batatasframework.support.database.values.BooleanValueHolder;
import org.batatasframework.support.database.values.DateValueHolder;
import org.batatasframework.support.database.values.DecimalValueHolder;
import org.batatasframework.support.database.values.FieldValue;
import org.batatasframework.support.database.values.FieldValueHolder;
import org.batatasframework.support.database.values.NumberValueHolder;
import org.batatasframework.support.database.values.ObjectValueHolder;
import org.batatasframework.support.database.values.StringValueHolder;
import org.batatasframework.support.type.JavaType;

import cn.bonoon.kernel.util.Opt;

/**
 * <pre>
 * 对应的数据库的通配类型
 * </pre>
 * @author jackson
 *
 */
public enum DatabaseType {
	
	STRING(JavaType.STRING, Opt.NULL, Opt.NN, Opt.EQ, Opt.NE, Opt.LIKE, Opt.LL, Opt.RL, Opt.IN, Opt.NI) {
		@Override
		public FieldValueHolder buildValueHolder(SelectFragment field, String alias, Object format) {
			return new StringValueHolder(field, alias, format);
		}

		@Override
		public QueryParameter buildQueryParameter(int index, Opt opt, Object value) {
			if(value instanceof String){
				if(opt == Opt.LL || opt == Opt.LIKE){
					value += "%";
				}
				if(opt == Opt.RL || opt == Opt.LIKE){
					value = "%" + value;
				}
				return new StringParamenter(index, value.toString());
			}
			return buildQueryParameter(index, opt, value.toString());
		}

//		@Override
//		public QueryParameter buildQueryParameter(int index, Opt opt, String value) {
//			
//		}
	},
	BOOLEAN(JavaType.BOOLEAN, Opt.NULL, Opt.NN, Opt.EQ, Opt.NE, Opt.IN, Opt.NI) {
		@Override
		public FieldValueHolder buildValueHolder(SelectFragment field, String alias, Object format) {
			return new BooleanValueHolder(field, alias, format);
		}

		@Override
		public QueryParameter buildQueryParameter(int index, Opt opt, Object value) {
			return new NumberParamenter(index, value);
		}

//		@Override
//		public QueryParameter buildQueryParameter(int index, Opt opt, String value) {
//			return new NumberParamenter(index, value);
//		}
	},
	NUMBER(JavaType.NUMBER, Opt.NULL, Opt.NN, Opt.EQ, Opt.NE, Opt.GE, Opt.GT, Opt.LE, Opt.LT, Opt.IN, Opt.NI) {
		
		@Override
		public FieldValueHolder buildValueHolder(SelectFragment field, String alias, Object format) {
			return new NumberValueHolder(field, alias, format);
		}
		
		@Override
		public QueryParameter buildQueryParameter(int index, Opt opt, Object value) {
			return new NumberParamenter(index, value);
		}

//		@Override
//		public QueryParameter buildQueryParameter(int index, Opt opt, String value) {
//			return new NumberParamenter(index, value);
//		}
	},
	DECIMAL(JavaType.DECIMAL, Opt.NULL, Opt.NN, Opt.EQ, Opt.NE, Opt.GE, Opt.GT, Opt.LE, Opt.LT, Opt.IN, Opt.NI) {
		
		@Override
		public FieldValueHolder buildValueHolder(SelectFragment field, String alias, Object format) {
			return new DecimalValueHolder(field, alias, format);
		}

		@Override
		public QueryParameter buildQueryParameter(int index, Opt opt, Object value) {
			return new DecimalParamenter(index, value);
		}

//		@Override
//		public QueryParameter buildQueryParameter(int index, Opt opt, String value) {
//			return new DecimalParamenter(index, value);
//		}
	},
	DATE(JavaType.DATE, Opt.NULL, Opt.NN, Opt.EQ, Opt.NE, Opt.GE, Opt.GT, Opt.LE, Opt.LT) {
		
		@Override
		public FieldValueHolder buildValueHolder(SelectFragment field, String alias, Object format) {
			return new DateValueHolder(field, alias, format);
		}

		@Override
		public QueryParameter buildQueryParameter(int index, Opt opt, Object value) {
			return new DatetimeParamenter(index, value);
		}

//		@Override
//		public QueryParameter buildQueryParameter(int index, Opt opt, String value) {
//			return new DatetimeParamenter(index, value);
//		}
	},
	TIME(JavaType.DATE, Opt.NULL, Opt.NN, Opt.EQ, Opt.NE, Opt.GE, Opt.GT, Opt.LE, Opt.LT) {
		@Override
		public FieldValueHolder buildValueHolder(SelectFragment field, String alias, Object format) {
			return new DateValueHolder(field, alias, format){
				@Override
				public FieldValue read(ResultSet rs) throws Exception {
					return new DateValue(rs.getTime(alias));
				}
			};
		}

		@Override
		public QueryParameter buildQueryParameter(int index, Opt opt, Object value) {
			return new DatetimeParamenter(index, value);
		}

//		@Override
//		public QueryParameter buildQueryParameter(int index, Opt opt, String value) {
//			return new DatetimeParamenter(index, value);
//		}
	},
	TIMESTAMP(JavaType.DATE, Opt.NULL, Opt.NN, Opt.EQ, Opt.NE, Opt.GE, Opt.GT, Opt.LE, Opt.LT) {
		@Override
		public FieldValueHolder buildValueHolder(SelectFragment field, String alias, Object format) {
			return new DateValueHolder(field, alias, format){
				@Override
				public FieldValue read(ResultSet rs) throws Exception {
					return new DateValue(rs.getTimestamp(alias));
				}
			};
		}

		@Override
		public QueryParameter buildQueryParameter(int index, Opt opt, Object value) {
			return new DatetimeParamenter(index, value);
		}

//		@Override
//		public QueryParameter buildQueryParameter(int index, Opt opt, String value) {
//			return new DatetimeParamenter(index, value);
//		}
	},
	OBJECT(JavaType.OBJECT, Opt.NULL, Opt.NN) {
		@Override
		public FieldValueHolder buildValueHolder(SelectFragment field, String alias, Object format) {
			return new ObjectValueHolder(field, alias);
		}
		
		@Override
		public QueryParameter buildQueryParameter(int index, Opt opt, Object value) {
			return new ObjectParamenter(index, value);
		}

//		@Override
//		public QueryParameter buildQueryParameter(int index, Opt opt, String value) {
//			return new ObjectParamenter(index, value);
//		}
	};
	private final Opt[] opts;
	private JavaType javaType;
	
	private DatabaseType(JavaType javaType, Opt... opts){
		this.javaType = javaType;
		this.opts = opts;
	}
	
	public abstract FieldValueHolder buildValueHolder(SelectFragment field, String alias, Object format);
	
	public abstract QueryParameter buildQueryParameter(int index, Opt opt, Object value);
//	public abstract QueryParameter buildQueryParameter(int index, Opt opt, String value);

	public Opt[] getOpts() {
		return opts;
	}
	
	public JavaType getJavaType() {
		return javaType;
	}
}
